To start off with, let’s load data and libs:

Some initial filters

Take highest read-depth call for multiply-genotyped DNA_IDs

I’m not sure if there are any of these, but best to leave it in here… if an individual is multiply-genotyped, take the genotype with the highest total read depth.

Remove the 6 loci which Hayley has been removing

# read in a list of the 6 loci
to_remove <- read_csv("../data/loci_to_remove.csv")
Parsed with column specification:
cols(
  locus = col_character()
)
# only keep the loci that are not those 6
keepers <- geno_one_each %>%
  anti_join(., to_remove, by = "locus")

that should leave 90 loci

Toss out indivs with data at fewer than 25 loci

Now, toss out any individual with fewer than 25 non-missing loci

no_hi_missers <- keepers %>% 
  group_by(NMFS_DNA_ID) %>%
  filter(sum(!is.na(allele)) >= (25*2))

So, we started with 12852 and after filtering out indivs with fewer than 75 genotyped loci, we were left with 12741 individuals. Those are the ones that we will run through rubias to identify to species.

Read in baseline genotypes and remove loci and individuals with too much missing data

From the .csv output from microhaplot, we need to reformat the data for rubias.

# add reference column to prepare data for rubias
spp.id_loc1 <- spp.id_loc %>%
  mutate(sample_type = "reference")
# add the repunit column that is identical to the group in this case
x <- spp.id_loc1 %>%
  mutate(repunit = group)
# reorder the columns and get the data frame in the right format
spp.id1 <- x[,c(6,7,1,3,2,4:5)]
spp.id2 <- spp.id1 %>%
  rename(collection = group) %>%
  rename(indiv = indiv.ID)

To ensure that haplotypes are coded identically across both the reference and mixture genotypes, we need to combine the two data sets, and then change haplotypes into numeric alleles.

str(alleles)
Classes ‘tbl_df’, ‘tbl’ and 'data.frame':   2548448 obs. of  7 variables:
 $ sample_type: chr  "reference" "reference" "reference" "reference" ...
 $ repunit    : chr  "Sauriculatus" "Sauriculatus" "Sauriculatus" "Sauriculatus" ...
 $ collection : chr  "Sauriculatus" "Sauriculatus" "Sauriculatus" "Sauriculatus" ...
 $ indiv      : chr  "s1" "s1" "s1" "s1" ...
 $ locus      : chr  "Plate_1_A01_Sat_GW603857_consensus" "Plate_1_A11_Sat_GE820299_consensus" "Plate_2_A09_Sat_EW986980_consensus" "Plate_2_C08_Sat_EW987116_consensus" ...
 $ gene_copy  : num  1 1 1 1 1 1 1 1 1 1 ...
 $ allele     : chr  "ACTAGCGTT" "CGGCTCCGGGTATCT" "CGAGATAGXGTCTGTT" "AGACTTCGG" ...

Here we turn alleles into integers, spread the data frame, and then get it into the right format to run rubias:

We will use infer_mixture in rubias, which requires two separate data frames, one with the reference genotypes and the other with the mixture.

I’ll split the data frame that I created (but it needed to be bunged together for the conversion of alleles to integers).

Now, with the two data frames separated, run the infer mixture analysis:

The posterior means of group membership in each collection is in the PofZ column.

Make a quick little plot to display the diversity of species in our NSF juvenile samples.

# ordered by number of samples
ggplot(grp_tally2, (aes(x = reorder(repunit, -n), y = n))) + 
  geom_bar(stat = "identity") +
  theme_bw() +
  ylab("Samples") +
  xlab("Species") +
  theme(
    axis.text.x = element_text(angle = 45, size = 16),
    axis.text.y = element_text(size = 16),
    axis.title = element_text(size = 18)) +
  scale_color_brewer(palette = "Set1")
  
ggsave("pdf_outputs/nsf_juv_id.pdf", height = 7, width = 12)

# There are individual assignments for each sample to each reference.
# If I want to keep the top assignment for each sample:
kept_assignments <- mix_assign$indiv_posteriors %>%
  group_by(indiv) %>%
  filter(PofZ > 0.5) %>%
  arrange(desc(PofZ))
kept_assignments

Picking out the gopher, black-and-yellow, and copper rockfishes

Interesting to see all the other species in there - mostly china and quillback. (And in reality, these non-target species only make up 1-2% of samples.)

But what we actually want is a list of NMFS IDs for the fish assigned to gopher, black-and-yellow, and copper, which we can then use to select those fish from our NSF dataset, where we presumably have many more alleles for those species because the VCF used to call genotypes included hundreds of samples for each of those species.

This dataset includes 12,741 samples.

That’s 7,519 samples.

LS0tCnRpdGxlOiAiYXNzaWduIG5vbi10YXJnZXQgZ29waGVyLWJsYWNrLWFuZC15ZWxsb3cgcm9ja2Zpc2ggd2l0aCBydWJpYXMiCm91dHB1dDogaHRtbF9ub3RlYm9vawotLS0KClRvIHN0YXJ0IG9mZiB3aXRoLCBsZXQncyBsb2FkIGRhdGEgYW5kIGxpYnM6CmBgYHtyIGxvYWQtc3R1ZmZ9CmxpYnJhcnkodGlkeXZlcnNlKQpsaWJyYXJ5KENLTVJzaW0pCmxpYnJhcnkoc3RyaW5ncikKbGlicmFyeShyZWFkeGwpCmxpYnJhcnkocnViaWFzKQoKI21ldGEgPC0gcmVhZFJEUygiLi4vZGF0YS9wcm9jZXNzZWQvbWV0YS1kYXRhLXRpYmJsZS5yZHMiKSAjIG5vdCB3b3JyeWluZyBhYm91dCBtZXRhIGRhdGEgcmlnaHQgbm93Li4uCmdlbm9zIDwtIHJlYWRSRFMoIi4uL25zZl9kYXRhL3Byb2Nlc3NlZC9jYWxsZWRfZ2Vub3NfbmFfZXhwbGljaXQucmRzIikgJT4lCiAgZmlsdGVyKE5NRlNfRE5BX0lEICE9ICJNb3JpbiIpICMgcmVtb3ZlIHRoZSBkYXRhIGZvciBQaGlsIE1vcmluCnNhbXBsZXMgPC0gcmVhZFJEUygiLi4vbnNmX2RhdGEvcHJvY2Vzc2VkL3NhbXBsZS1zaGVldC10aWJibGUucmRzIikgIyU+JQogICNmaWx0ZXIoTk1GU19ETkFfSUQgJWluJSBtZXRhJE5NRlNfRE5BX0lEKQogIApgYGAKCiMjIFNvbWUgaW5pdGlhbCBmaWx0ZXJzCgojIyMgVGFrZSBoaWdoZXN0IHJlYWQtZGVwdGggY2FsbCBmb3IgbXVsdGlwbHktZ2Vub3R5cGVkIEROQV9JRHMKCkknbSBub3Qgc3VyZSBpZiB0aGVyZSBhcmUgYW55IG9mIHRoZXNlLCBidXQgYmVzdCB0byBsZWF2ZSBpdCBpbiBoZXJlLi4uCmlmIGFuIGluZGl2aWR1YWwgaXMgbXVsdGlwbHktZ2Vub3R5cGVkLCB0YWtlIHRoZQpnZW5vdHlwZSB3aXRoIHRoZSBoaWdoZXN0IHRvdGFsIHJlYWQgZGVwdGguICAKYGBge3IgdGFrZS1qdXN0LW9uZX0KIyBzbG93LWlzaCBmdW5jdGlvbiB0byBnZXQgdGhlIHRvdGFsIHJlYWQgZGVwdGggY29sdW1uCnRkZXB0aCA8LSBmdW5jdGlvbihhLCBkKSB7CiAgaWYoYW55KGlzLm5hKGEpKSkgewogICAgcmV0dXJuKE5BKQogIH0KICBpZihhWzFdPT1hWzJdKSB7CiAgICByZXR1cm4oZFsxXSkKICB9IGVsc2UgewogICAgcmV0dXJuKGRbMV0gKyBkWzJdKQogIH0KICAKfQojIHRoaXMgdGFrZXMgdGhlIGhpZ2hlc3QgcmVhZC1kZXB0aCBpbnN0YW5jZSBvZiBlYWNoIGR1cGxpY2F0ZWx5LWdlbm90eXBlZCBpbmRpdmlkdWFsLgpnZW5vX29uZV9lYWNoIDwtIGdlbm9zICU+JQogIGdyb3VwX2J5KE5NRlNfRE5BX0lELCBsb2N1cywgZ3RzZXFfcnVuLCBpZCkgJT4lCiAgbXV0YXRlKHRvdGFsX2RlcHRoID0gdGRlcHRoKGFsbGVsZSwgZGVwdGgpKSAlPiUKICB1bmdyb3VwKCkgJT4lCiAgYXJyYW5nZShOTUZTX0ROQV9JRCwgbG9jdXMsIHRvdGFsX2RlcHRoLCBndHNlcV9ydW4sIGlkLCBkZXB0aCkgJT4lCiAgZ3JvdXBfYnkoTk1GU19ETkFfSUQsIGxvY3VzKSAlPiUKICBtdXRhdGUocmFuayA9IDE6bigpKSAlPiUKICB1bmdyb3VwKCkgJT4lCiAgZmlsdGVyKHJhbmsgPD0gMikKYGBgCgoKIyMjIFJlbW92ZSB0aGUgNiBsb2NpIHdoaWNoIEhheWxleSBoYXMgYmVlbiByZW1vdmluZwoKYGBge3IgcmVtb3ZlLWxvY2l9CiMgcmVhZCBpbiBhIGxpc3Qgb2YgdGhlIDYgbG9jaQp0b19yZW1vdmUgPC0gcmVhZF9jc3YoIi4uL2RhdGEvbG9jaV90b19yZW1vdmUuY3N2IikKCiMgb25seSBrZWVwIHRoZSBsb2NpIHRoYXQgYXJlIG5vdCB0aG9zZSA2CmtlZXBlcnMgPC0gZ2Vub19vbmVfZWFjaCAlPiUKICBhbnRpX2pvaW4oLiwgdG9fcmVtb3ZlLCBieSA9ICJsb2N1cyIpCmBgYAp0aGF0IHNob3VsZCBsZWF2ZSA5MCBsb2NpICAKCiMjIyBUb3NzIG91dCBpbmRpdnMgd2l0aCBkYXRhIGF0IGZld2VyIHRoYW4gMjUgbG9jaQpOb3csIHRvc3Mgb3V0IGFueSBpbmRpdmlkdWFsIHdpdGggZmV3ZXIgdGhhbiAyNSBub24tbWlzc2luZyBsb2NpCmBgYHtyIHRvc3MtbWlzc2Vyc30Kbm9faGlfbWlzc2VycyA8LSBrZWVwZXJzICU+JSAKICBncm91cF9ieShOTUZTX0ROQV9JRCkgJT4lCiAgZmlsdGVyKHN1bSghaXMubmEoYWxsZWxlKSkgPj0gKDI1KjIpKQpgYGAKU28sIHdlIHN0YXJ0ZWQgd2l0aCBgciBsZW5ndGgodW5pcXVlKGdlbm9fb25lX2VhY2gkTk1GU19ETkFfSUQpKWAgCmFuZCBhZnRlciBmaWx0ZXJpbmcgb3V0IGluZGl2cyB3aXRoIGZld2VyIHRoYW4gNzUgZ2Vub3R5cGVkIGxvY2ksIHdlIHdlcmUgbGVmdCB3aXRoIApgciBsZW5ndGgodW5pcXVlKG5vX2hpX21pc3NlcnMkTk1GU19ETkFfSUQpKWAgaW5kaXZpZHVhbHMuICBUaG9zZSBhcmUgdGhlIG9uZXMgdGhhdAp3ZSB3aWxsIHJ1biB0aHJvdWdoIHJ1YmlhcyB0byBpZGVudGlmeSB0byBzcGVjaWVzLgoKIyMgUmVhZCBpbiBiYXNlbGluZSBnZW5vdHlwZXMgYW5kIHJlbW92ZSBsb2NpIGFuZCBpbmRpdmlkdWFscyB3aXRoIHRvbyBtdWNoIG1pc3NpbmcgZGF0YQoKYGBge3IgcmVhZC1zcHAtZ2Vub3N9CiMgcmVhZCBpbiBnZW5vdHlwZXMgaWRlbnRpZmllZCB0byBzcGVjaWVzIHVzaW5nIHJ1YmlhcwpzcHAgPC0gcmVhZF9jc3YoIi4uL2RhdGEvcmVwb3J0ZWRfaGFwbG90eXBlX1NlYlNwcElEXzExMTAyMDE3LmNzdiIpCgpzZWxlY3Rfc3BwIDwtIHNwcCAlPiUKICBzZWxlY3QoZ3JvdXAsIGxvY3VzLCBpbmRpdi5JRCwgaGFwbG90eXBlLjEsIGhhcGxvdHlwZS4yKQoKc3BwLmlkIDwtIHNlbGVjdF9zcHAgJT4lCiAgZ2F0aGVyKCJnZW5lX2NvcHkiLCAiYWxsZWxlIiwgNDo1KSAlPiUKICBtdXRhdGUoZ2VuZV9jb3B5ID0gaWZlbHNlKGdlbmVfY29weSA9PSAiaGFwbG90eXBlLjEiLCAxLCAyKSkKCiMgb25seSBrZWVwIHRoZSBsb2NpIHRoYXQgYXJlIG5vdCB0aGUgNiByZW1vdmVkIGZyb20gdGhlIHByZXZpb3VzIGRhdGFzZXQKc3BwLmlkX2xvYyA8LSBzcHAuaWQgJT4lCiAgYW50aV9qb2luKC4sIHRvX3JlbW92ZSwgYnkgPSAibG9jdXMiKQojIHRoYXQgc2hvdWxkIGxlYXZlIDkwIGxvY2kgCmBgYAoKRnJvbSB0aGUgLmNzdiBvdXRwdXQgZnJvbSBtaWNyb2hhcGxvdCwgd2UgbmVlZCB0byByZWZvcm1hdCB0aGUgZGF0YSBmb3IgcnViaWFzLgpgYGB7ciBmb3JtYXQtcmVmZXJlbmNlLWZvci1ydWJpYXN9CiMgYWRkIHJlZmVyZW5jZSBjb2x1bW4gdG8gcHJlcGFyZSBkYXRhIGZvciBydWJpYXMKc3BwLmlkX2xvYzEgPC0gc3BwLmlkX2xvYyAlPiUKICBtdXRhdGUoc2FtcGxlX3R5cGUgPSAicmVmZXJlbmNlIikKCiMgYWRkIHRoZSByZXB1bml0IGNvbHVtbiB0aGF0IGlzIGlkZW50aWNhbCB0byB0aGUgZ3JvdXAgaW4gdGhpcyBjYXNlCnggPC0gc3BwLmlkX2xvYzEgJT4lCiAgbXV0YXRlKHJlcHVuaXQgPSBncm91cCkKCiMgcmVvcmRlciB0aGUgY29sdW1ucyBhbmQgZ2V0IHRoZSBkYXRhIGZyYW1lIGluIHRoZSByaWdodCBmb3JtYXQKc3BwLmlkMSA8LSB4WyxjKDYsNywxLDMsMiw0OjUpXQpzcHAuaWQyIDwtIHNwcC5pZDEgJT4lCiAgcmVuYW1lKGNvbGxlY3Rpb24gPSBncm91cCkgJT4lCiAgcmVuYW1lKGluZGl2ID0gaW5kaXYuSUQpCmBgYAoKVG8gZW5zdXJlIHRoYXQgaGFwbG90eXBlcyBhcmUgY29kZWQgaWRlbnRpY2FsbHkgYWNyb3NzIGJvdGggdGhlIHJlZmVyZW5jZSBhbmQgbWl4dHVyZSBnZW5vdHlwZXMsIHdlIG5lZWQgdG8gY29tYmluZSB0aGUgdHdvIGRhdGEgc2V0cywgYW5kIHRoZW4gY2hhbmdlIGhhcGxvdHlwZXMgaW50byBudW1lcmljIGFsbGVsZXMuCmBgYHtyIGZvcm1hdC10aGUtbWl4dHVyZX0KIyBnZXQgdGhlIHJlZmVyZW5jZSBhbmQgbWl4dHVyZSBkYXRhIGZyYW1lcyBpbnRvIHRoZSBzYW1lIGZvcm1hdApub19oaV9taXNzZXJzMiA8LSBub19oaV9taXNzZXJzICU+JQogIGRwbHlyOjpzZWxlY3QoTk1GU19ETkFfSUQsIGxvY3VzLCBnZW5lX2NvcHksIGFsbGVsZSkgJT4lCiAgcmVuYW1lKGluZGl2ID0gTk1GU19ETkFfSUQpICU+JQogIG11dGF0ZShzYW1wbGVfdHlwZSA9ICJtaXh0dXJlIikgJT4lCiAgbXV0YXRlKHJlcHVuaXQgPSBOQSkgJT4lCiAgbXV0YXRlKGNvbGxlY3Rpb24gPSAibnNmX3NhbXBsZXMiKQoKIyByZW9yZGVyIHRoZSBjb2x1bW5zIGZvciB0aGUgbWl4dHVyZSBkYXRhIGZyYW1lCm5vX2hpX21pc3NlcnMzIDwtIG5vX2hpX21pc3NlcnMyWywgYyg1OjcsMTo0KV0KCiMgY29tYmluZSBib3RoIGRhdGEgc2V0cyBpbnRvIGEgc2luZ2xlIGRmCmFsbGVsZXMgPC0gYmluZF9yb3dzKHNwcC5pZDIsIG5vX2hpX21pc3NlcnMzKQoKYGBgCgoKCkhlcmUgd2UgdHVybiBhbGxlbGVzIGludG8gaW50ZWdlcnMsIHNwcmVhZCB0aGUgZGF0YSBmcmFtZSwgYW5kIHRoZW4gZ2V0IGl0IGludG8gdGhlIHJpZ2h0IGZvcm1hdCB0byBydW4gcnViaWFzOgpgYGB7ciBzcHJlYWQtZ2Vub3N9CiMgZmlyc3QgbWFrZSBpbnRlZ2VycyBvZiB0aGUgYWxsZWxlcwphbGxlX2lkeHMgPC0gYWxsZWxlcyAlPiUgCiAgI3NlbGVjdChOTUZTX0ROQV9JRCwgbG9jdXMsIGdlbmVfY29weSwgYWxsZWxlKSAlPiUKICBncm91cF9ieShsb2N1cykgJT4lCiAgbXV0YXRlKGFsbGVpZHggPSBhcy5pbnRlZ2VyKGZhY3RvcihhbGxlbGUsIGxldmVscyA9IHVuaXF1ZShhbGxlbGUpKSkpICU+JQogIHVuZ3JvdXAoKSAlPiUKICBhcnJhbmdlKGluZGl2LCBsb2N1cywgYWxsZWlkeCkgIyBydWJpYXMgY2FuIGhhbmRsZSBOQSdzLCBzbyBubyBuZWVkIHRvIGNoYW5nZSB0aGVtIHRvIDAncwogIAojIHNlbGVjdCBqdXN0IHRoZSBjb2x1bW5zIHRvIHJldGFpbiBhbmQgc3ByZWFkIHRoZSBhbGxlbGVzCmFsbGVfaWR4MiA8LSBhbGxlX2lkeHNbLC03XQogIAp0d29fY29sIDwtIGFsbGVfaWR4MiAlPiUKICB1bml0ZShsb2MsIGxvY3VzLCBnZW5lX2NvcHksIHNlcCA9ICIuIikgJT4lCiAgc3ByZWFkKGxvYywgYWxsZWlkeCkKCiMgd3JpdGUgdGhpcyBmaWxlIHRvIGEgdGhpbmcgdGhhdCBjYW4gYmUgcmVhZC1pbnRvIG90aGVyIHNvZnR3YXJlcwojdHdvX2NvbCAlPiUKIyB3cml0ZV9jc3YoImNzdl9vdXRwdXRzL2dlbm9zX3R3b19jb2wuY3N2IikKYGBgCgpXZSB3aWxsIHVzZSBgaW5mZXJfbWl4dHVyZWAgaW4gcnViaWFzLCB3aGljaCByZXF1aXJlcyB0d28gc2VwYXJhdGUgZGF0YSBmcmFtZXMsIG9uZSB3aXRoIHRoZSByZWZlcmVuY2UgZ2Vub3R5cGVzIGFuZCB0aGUgb3RoZXIgd2l0aCB0aGUgbWl4dHVyZS4gCgpJJ2xsIHNwbGl0IHRoZSBkYXRhIGZyYW1lIHRoYXQgSSBjcmVhdGVkIChidXQgaXQgbmVlZGVkIHRvIGJlIGJ1bmdlZCB0b2dldGhlciBmb3IgdGhlIGNvbnZlcnNpb24gb2YgYWxsZWxlcyB0byBpbnRlZ2VycykuCmBgYHtyIHNwbGl0LWZyYW1lc30KIyBzcGxpdCB1cCB0aGUgcmVmZXJlbmNlIGFuZCBtaXh0dXJlIGRhdGEgZnJhbWVzCnNwX21peCA8LSB0d29fY29sICU+JQogIGZpbHRlcihzYW1wbGVfdHlwZSA9PSAibWl4dHVyZSIpCgpzcF9yZWYgPC0gdHdvX2NvbCAlPiUKICBmaWx0ZXIoc2FtcGxlX3R5cGUgPT0gInJlZmVyZW5jZSIpCmBgYAoKTm93LCB3aXRoIHRoZSB0d28gZGF0YSBmcmFtZXMgc2VwYXJhdGVkLCBydW4gdGhlIGBpbmZlciBtaXh0dXJlYCBhbmFseXNpczoKYGBge3IgcnVuLW1peHR1cmV9CiMgcGVyZm9ybSBtaXh0dXJlLWFzc2lnbm1lbnQgb24gYmFzZWxpbmUgY29sb255IHNhbXBsZXMKbWl4X2Fzc2lnbiA8LSBpbmZlcl9taXh0dXJlKHJlZmVyZW5jZSA9IHNwX3JlZiwgbWl4dHVyZSA9IHNwX21peCwgZ2VuX3N0YXJ0X2NvbCA9IDUsIG1ldGhvZCA9ICJNQ01DIiwgcmVwcyA9IDIwMDAsIGJ1cm5faW4gPSAxMDApCgojIFRoYXQgd2FzIGZhc3QsIGxldCdzIHRha2UgYSBsb29rCmhlYWQobWl4X2Fzc2lnbikKCiMgdGhlIGluZGl2aWR1YWwgZGF0YSBpcyBpbiAKbWl4X2Fzc2lnbiRpbmRpdl9wb3N0ZXJpb3JzICU+JQogIGFycmFuZ2UoZGVzYyhsb2dfbGlrZWxpaG9vZCkpCgojIGxvb2sgYXQgdGhlIGZpc2ggdGhhdCB3ZXJlIGFzc2lnbmVkIHdpdGggOTUlIGNvbmZpZGVuY2UKbnNmX2Fzc2lnbm1lbnRzIDwtIG1peF9hc3NpZ24kaW5kaXZfcG9zdGVyaW9ycyAlPiUKICBmaWx0ZXIoUG9mWiA+IDAuOTUpIAoKZ3JwX3RhbGx5IDwtIG5zZl9hc3NpZ25tZW50c1ssLTEwXSAlPiUgIyBkcm9wIHRoZSBtaXNzaW5nIGxvY2kgY29sdW1uIAogIGZpbHRlcih6X3Njb3JlID4gLTIgJiB6X3Njb3JlIDwgMikgJT4lICMgb25seSB3aXRoaW4gMiBzdGFuZGFyZCBkZXZpYXRpb25zCiAgZ3JvdXBfYnkocmVwdW5pdCkgJT4lCiAgdGFsbHkoKQogICN3cml0ZV9jc3YoIi4uL25zZl9kYXRhL3NwcF9hc3NpZ25tZW50c18xLVBvZlpfenNjb3JlMi5jc3YiKQoKZ3JwX3RhbGx5MiA8LSBncnBfdGFsbHkgJT4lCiAgYXJyYW5nZShkZXNjKG4pKSAlPiUKICBmaWx0ZXIobiA+IDEpCiAgCmBgYApUaGUgcG9zdGVyaW9yIG1lYW5zIG9mIGdyb3VwIG1lbWJlcnNoaXAgaW4gZWFjaCBjb2xsZWN0aW9uIGlzIGluIHRoZSBQb2ZaIGNvbHVtbi4KCk1ha2UgYSBxdWljayBsaXR0bGUgcGxvdCB0byBkaXNwbGF5IHRoZSBkaXZlcnNpdHkgb2Ygc3BlY2llcyBpbiBvdXIgTlNGIGp1dmVuaWxlIHNhbXBsZXMuCmBgYHtyIHF1aWNrLXBsb3R9CiMgb3JkZXJlZCBieSBudW1iZXIgb2Ygc2FtcGxlcwpnZ3Bsb3QoZ3JwX3RhbGx5MiwgKGFlcyh4ID0gcmVvcmRlcihyZXB1bml0LCAtbiksIHkgPSBuKSkpICsgCiAgZ2VvbV9iYXIoc3RhdCA9ICJpZGVudGl0eSIpICsKICB0aGVtZV9idygpICsKICB5bGFiKCJTYW1wbGVzIikgKwogIHhsYWIoIlNwZWNpZXMiKSArCiAgdGhlbWUoCiAgICBheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDQ1LCBzaXplID0gMTYpLAogICAgYXhpcy50ZXh0LnkgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDE2KSwKICAgIGF4aXMudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDE4KSkgKwogIHNjYWxlX2NvbG9yX2JyZXdlcihwYWxldHRlID0gIlNldDEiKQoKICAKZ2dzYXZlKCJwZGZfb3V0cHV0cy9uc2ZfanV2X2lkLnBkZiIsIGhlaWdodCA9IDcsIHdpZHRoID0gMTIpCmBgYAoKYGBge3J9CiMgTm93IGp1c3QgdGhlIG5vbi1LR0JDCmdycF90YWxseTIgJT4lCiAgZmlsdGVyKHJlcHVuaXQgIT0gIlNhdHJvdmlyZW5zIiAmIHJlcHVuaXQgIT0gIlNjYXJuYXR1cyIgJiByZXB1bml0ICE9ICJTY2hyeXNvbWVsYXMiICYgcmVwdW5pdCAhPSJTY2F1cmludXMiKSAlPiUKICBnZ3Bsb3QoKGFlcyh4ID0gcmVvcmRlcihyZXB1bml0LCAtbiksIHkgPSBuKSkpICsgCiAgZ2VvbV9iYXIoc3RhdCA9ICJpZGVudGl0eSIpICsKICB0aGVtZV9idygpICsKICB5bGFiKCJTYW1wbGVzIikgKwogIHhsYWIoIlNwZWNpZXMiKSArCiAgdGhlbWUoCiAgICBheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDQ1LCBzaXplID0gMTYpLAogICAgYXhpcy50ZXh0LnkgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDE2KSwKICAgIGF4aXMudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDE4KSkgKwogIHNjYWxlX2NvbG9yX2JyZXdlcihwYWxldHRlID0gIlNldDEiKQoKCmdnc2F2ZSgicGRmX291dHB1dHMvbm9uX2tnYmNfanV2X2lkLnBkZiIsIGhlaWdodCA9IDcsIHdpZHRoID0gMTApCgoKZ3JwX3RhbGx5MiAlPiUKICBmaWx0ZXIocmVwdW5pdCAhPSAiU2F0cm92aXJlbnMiICYgcmVwdW5pdCAhPSAiU2Nhcm5hdHVzIiAmIHJlcHVuaXQgIT0gIlNjaHJ5c29tZWxhcyIgJiByZXB1bml0ICE9IlNjYXVyaW51cyIpICU+JSB1bmdyb3VwICU+JQogIGFycmFuZ2UoZGVzYyhuKSkKCgoKIyBtYXliZSBJIGNvdWxkIGNvbG9yIHRoZSBiYXJzIGlmIHRoZXkgYXJlIHBhcnQgb2YgdGhlIHB0ZXJvcG9kdXMgZmFtaWx5PwojIHB0ZXJvIDwtIGMoIlNhdHJvdmlyZW5zIiwgIlNjYXJuYXR1cyIsICJTY2F1cmludXMiLCAiU2Nocnlzb21lbGFzIiwgIlNuZWJ1bG9zdXMiKQojIAojIHB0ZXJvCmBgYAoKCmBgYHtyIGxlc3Nlci1hc3NpZ25tZW50c30KIyBUaGVyZSBhcmUgaW5kaXZpZHVhbCBhc3NpZ25tZW50cyBmb3IgZWFjaCBzYW1wbGUgdG8gZWFjaCByZWZlcmVuY2UuCiMgSWYgSSB3YW50IHRvIGtlZXAgdGhlIHRvcCBhc3NpZ25tZW50IGZvciBlYWNoIHNhbXBsZToKa2VwdF9hc3NpZ25tZW50cyA8LSBtaXhfYXNzaWduJGluZGl2X3Bvc3RlcmlvcnMgJT4lCiAgZ3JvdXBfYnkoaW5kaXYpICU+JQogIGZpbHRlcihQb2ZaID4gMC41KSAlPiUKICBhcnJhbmdlKGRlc2MoUG9mWikpCgprZXB0X2Fzc2lnbm1lbnRzCmBgYAoKIyMgUGlja2luZyBvdXQgdGhlIGdvcGhlciwgYmxhY2stYW5kLXllbGxvdywgYW5kIGNvcHBlciByb2NrZmlzaGVzCgpJbnRlcmVzdGluZyB0byBzZWUgYWxsIHRoZSBvdGhlciBzcGVjaWVzIGluIHRoZXJlIC0gbW9zdGx5IGNoaW5hIGFuZCBxdWlsbGJhY2suIChBbmQgaW4gcmVhbGl0eSwgdGhlc2Ugbm9uLXRhcmdldCBzcGVjaWVzIG9ubHkgbWFrZSB1cCAxLTIlIG9mIHNhbXBsZXMuKQoKQnV0IHdoYXQgd2UgYWN0dWFsbHkgd2FudCBpcyBhIGxpc3Qgb2YgTk1GUyBJRHMgZm9yIHRoZSBmaXNoIGFzc2lnbmVkIHRvIGdvcGhlciwgYmxhY2stYW5kLXllbGxvdywgYW5kIGNvcHBlciwgd2hpY2ggd2UgY2FuIHRoZW4gdXNlIHRvIHNlbGVjdCB0aG9zZSBmaXNoIGZyb20gb3VyIE5TRiBkYXRhc2V0LCB3aGVyZSB3ZSBwcmVzdW1hYmx5IGhhdmUgbWFueSBtb3JlIGFsbGVsZXMgZm9yIHRob3NlIHNwZWNpZXMgYmVjYXVzZSB0aGUgVkNGIHVzZWQgdG8gY2FsbCBnZW5vdHlwZXMgaW5jbHVkZWQgaHVuZHJlZHMgb2Ygc2FtcGxlcyBmb3IgZWFjaCBvZiB0aG9zZSBzcGVjaWVzLgoKVGhpcyBkYXRhc2V0IGluY2x1ZGVzIDEyLDc0MSBzYW1wbGVzLgpgYGB7cn0KIG1peF9hc3NpZ24kaW5kaXZfcG9zdGVyaW9ycyAlPiUKICBncm91cF9ieShpbmRpdikgJT4lCiAgZmlsdGVyKFBvZlogPiAwLjUpICU+JSAjIGtlZXAgYWxsIHBvdGVudGlhbCBhc3NpZ25tZW50cyB0byBjaGVjayBhZ2FpbiB3aXRoIEdTSSBTSU0gaW4gdGhlIG5zZiB3b3JrZmxvdwogIGZpbHRlcihjb2xsZWN0aW9uICVpbiUgYygiU2Nhcm5hdHVzIiwgIlNjaHJ5c29tZWxhcyIsICJTY2F1cmludXMiKSkgJT4lCiAgc2VsZWN0KGluZGl2KSAlPiUKICByZW5hbWUoTk1GU19ETkFfSUQgPSBpbmRpdikgJT4lCiAgd3JpdGVfY3N2KCJjc3Zfb3V0cHV0cy9uc2YtR0JZQy1zYW1wbGVzLWlkcy5jc3YiKQoKICAKYGBgClRoYXQncyA3LDUxOSBzYW1wbGVzLgoKCg==